<?php
/**
 * 贝灵斯 提现
 * */

namespace App\Lib;

use Illuminate\Support\Facades\Log;

class Bls
{
    //配置
    protected $selfConfig = [];

    // 构造
    public function __construct()
    {
        if (env('APP_ENV') != 'product') {
            $this->selfConfig = config('bls_dev') ?? [];
        } else {
            $this->selfConfig = config('bls') ?? [];
        }
    }
    /**
     * 转换PublicKey
     */
    public function convertPublicKey($publicKey) {
        //判断是否传入公钥内容
        $public_key_string = !empty($publicKey) ? $publicKey : '';
        //64位换行公钥钥内容
        $public_key_string = chunk_split($public_key_string, 64, "\r\n");
        //公钥头部
        $public_key_header = "-----BEGIN PUBLIC KEY-----\r\n";
        //公钥尾部
        $public_key_footer = "-----END PUBLIC KEY-----";
        //完整公钥拼接
        $public_key_string = $public_key_header.$public_key_string.$public_key_footer;
        return $public_key_string;
    }

    /**
     * RSA签名
     * @param $data 待签名数据
     * return 签名结果
     */
    public function rsaSign($data) {
        $private_key = $this->selfConfig['private_key'];
        $type = 'RSA2';

        $private_key = "-----BEGIN RSA PRIVATE KEY-----\n" .
                        wordwrap($private_key, 64, "\n", true) .
                        "\n-----END RSA PRIVATE KEY-----";
        $res = openssl_get_privatekey($private_key);
        if($res) {
            if($type == 'RSA'){
                openssl_sign($data, $sign,$res);
            }elseif($type == 'RSA2'){
                openssl_sign($data, $sign,$res,"SHA256");
            }
            openssl_free_key($res);
        } else {
            return '';
        }
        $sign = base64_encode($sign);
        return $sign;
    }

    /**
     * RSA验签
     * @param $data 待签名数据
     * return 签名结果
     */
    public function checkSign($sign,$str){
        $pubKey = $this->selfConfig['bls_public_key'];
        //转换成PublicKey格式
        $pubKey = $this->convertPublicKey($pubKey);
        //验签
        $result = openssl_verify($str, base64_decode($sign), $pubKey, 'SHA256');

        return $result;
    }

    //POST请求
    protected function curlPost($url, $httpHeader, $body) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeader);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //处理http证书问题
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $ret = curl_exec($ch);
        if (false === $ret) {
            $ret = curl_errno($ch);
        }

        // 截取响应头字符串，并转换为数组形式
        $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        curl_close($ch);
        $headerStr = mb_substr($ret, 0, $headerSize);
        $responseHeader = $this->headerHandler($headerStr);
        $responseBody = mb_substr($ret, $headerSize);

        return ['responseHeader'=>$responseHeader,'responseBody'=>$responseBody];
    }
    protected function headerHandler($headerStr) {
        $headerArr = explode("\r\n", $headerStr);
        if (empty($headerArr)) {
            return [];
        }
    
        $ret = [];
        foreach ($headerArr as $headerLine) {
            // HTTP响应头是以:分隔key和value的
            $split = explode(':', $headerLine, 2);
            if (count($split) > 1) {
                $key = trim($split[0]);
                $value = trim($split[1]);
                $ret[$key] = $value;
            }
        }
    
        return $ret;
    }

    /**
     * 请求格式化
     * */
    protected function doCurl($url, $body, $method='post')
    {
        $url = $this->selfConfig['domain'].$url;

        //加签
        $sign = json_encode($body);
        $sign = $this->rsaSign($sign);
        if(empty($sign)) {
            return [];
        }

        //头
        $httpHeader = [];
        $httpHeader[] = 'Content-Type:application/json;charset=utf-8';
        $httpHeader[] = 'X-Yzx-Signature:'.$sign;
        $httpHeader[] = 'X-Yzx-TenantId:'.$this->selfConfig['tenantId'];
        $httpHeader[] = 'X-Yzx-ClientNo:'.$this->selfConfig['clientNo'];
        
        //请求
        $result = $this->curlPost($url, $httpHeader, $body);
        if(empty($result['responseHeader']['X-Yzx-Signature'])) {
            write_log('bls', 'curlResult ERROR 无响应头', ['url'=>$url, 'httpHeader'=>$httpHeader, 'body'=>$body, 'result'=>$result]);
            return [];
        }
        $sign = $result['responseHeader']['X-Yzx-Signature'];
        $result = json_decode($result['responseBody'], true);
        //验签
        $check = $this->checkSign($sign, json_encode($result, JSON_UNESCAPED_UNICODE));
        if(!$check) {
            write_log('bls', 'curlResult ERROR 验签失败', ['url'=>$url, 'httpHeader'=>$httpHeader, 'body'=>$body, 'result'=>$result, 'sign'=>$sign]);
            return [];
        }
        write_log('bls', 'curlResult', ['url'=>$url, 'httpHeader'=>$httpHeader, 'body'=>$body, 'result'=>$result]);

        return $result;
    }

    /**
     * 自由职业者签约
     * */
    public function workerRegister($body)
    {
        $url = "/api/worker/register";
        $body['version'] = '1.0';
        $body['clientNo'] = $this->selfConfig['clientNo'];

        $result = $this->doCurl($url, $body);
        if(!empty($result['failList'])) {
            $result['code'] = -1;
            $result['msg'] = $result['failList'][0]['errorMsg'];
        }

        return $result;
    }

    /**
     * 需求任务创建
     * */
    public function taskelease($body)
    {
        $url = "/api/task/release";
        $body['version'] = '1.0';
        $body['clientNo'] = $this->selfConfig['clientNo'];
        $body['tenantId'] = $this->selfConfig['tenantId'];
        $body['taskName'] = '创建任务';
        $body['taskVocation'] = 'hlw';
        $body['channelNo'] = $this->selfConfig['channelNo'];
        $body['taskStartDate'] = date("Ymd", time());
        $body['taskEndDate'] = date("Ymd", (time()+3600));

        $result = $this->doCurl($url, $body);
        if(!empty($result['failList'])) {
            $result['code'] = -1;
            $result['msg'] = $result['failList'][0]['errorMsg'];
        }

        return $result;
    }

    /**
     * 发佣发起
     * */
    public function payCreate($body)
    {
        $url = "/api/pay/create";
        $body['version'] = '1.0';
        $body['clientNo'] = $this->selfConfig['clientNo'];
        $body['taskNo'] = $this->selfConfig['taskNo'];

        $result = $this->doCurl($url, $body);
        if(!empty($result['failList'])) {
            $result['code'] = -1;
            $result['msg'] = $result['failList'][0]['errorMsg'];
        }

        return $result;
    }


}